﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using EStart.Infrastructure.ClientData;
using System.Web;
using Edu.Api.Authentication;
using EStart.Infrastructure.Caching;
using EStart.Infrastructure.Engines;
using System.Collections.Specialized;
using System.Text;
using System.IO;

namespace Edu.Api.Filters
{
    public class APISecurityFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            ApiResult<string> result = null;
            var request = context.HttpContext.Request;
            string method = request.Method;
            string staffid = String.Empty,
                timestamp = string.Empty,
                nonce = string.Empty,
                signature = string.Empty;
            Guid id = Guid.NewGuid();

            #region GET headers params
            var hStaffid = context.HttpContext.Request.Headers["staffid"];
            if (hStaffid.Count > 0)
            {
                staffid = HttpUtility.UrlDecode(hStaffid.FirstOrDefault());
            }
            var hTimestamp = context.HttpContext.Request.Headers["timestamp"];
            if (hTimestamp.Count > 0)
            {
                timestamp = HttpUtility.UrlDecode(hTimestamp.FirstOrDefault());
            }
            var hNonce = context.HttpContext.Request.Headers["nonce"];
            if (hNonce.Count > 0)
            {
                nonce = HttpUtility.UrlDecode(hNonce.FirstOrDefault());
            }
            var hSignature = context.HttpContext.Request.Headers["signature"];
            if (hSignature.Count > 0)
            {
                signature = HttpUtility.UrlDecode(hSignature.FirstOrDefault());
            }
            #endregion


            var actionName = context.ActionDescriptor.RouteValues["action"];
            // 要过滤的action
            var ignoreActions = new List<string>
                {
                    "Login",
                    "Logout"
                };
            if (ignoreActions.Any(p => p == actionName))
            {
                if (string.IsNullOrEmpty(staffid) || (!Guid.TryParse(staffid, out id) || string.IsNullOrEmpty(timestamp) || string.IsNullOrEmpty(nonce)))
                {
                    result = new ApiResult<string>
                    {
                        statusCode = (int)StatusCodeEnum.ParameterError,
                        message = StatusCodeEnum.ParameterError.GetEnumText(),
                        data = ""
                    };
                    context.Result = new JsonResult(result);
                    base.OnActionExecuting(context);
                    return;
                }
                else
                {
                    base.OnActionExecuting(context);
                    return;
                }
            }
            //判断请求头是否包含以下参数
            if (string.IsNullOrEmpty(staffid) ||
                (!Guid.TryParse(staffid, out id) ||
                string.IsNullOrEmpty(timestamp) ||
                string.IsNullOrEmpty(nonce) ||
                string.IsNullOrEmpty(signature)))
            {
                result = new ApiResult<string>
                {
                    statusCode = (int)StatusCodeEnum.ParameterError,
                    message = StatusCodeEnum.ParameterError.GetEnumText(),
                    data = ""
                };
                context.Result = new JsonResult(result);
                base.OnActionExecuting(context);
                return;
            }
            //判断timespan是否有效
            double ts2 = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds;
            bool timespanvalidate = double.TryParse(timestamp, out double ts1);
            double ts = ts2 - ts1;
            var urlExpireTime = 120;//后期需读取配置文件
            bool falg = ts > urlExpireTime * 1000;
            if (falg || (!timespanvalidate))
            {
                result = new ApiResult<string>
                {
                    statusCode = (int)StatusCodeEnum.URLExpireError,
                    message = StatusCodeEnum.URLExpireError.GetEnumText(),
                    data = ""
                };
                context.Result = new JsonResult(result);
                base.OnActionExecuting(context);
                return;
            }

            //判断token是否有效
            var cacheManager = EngineContainerFactory.Context.GetInstance<ICacheManager>();
            var token = cacheManager.Get<Token>(id.ToString());
            string signtoken = string.Empty;
            if (token == null)
            {
                result = new ApiResult<string>
                {
                    statusCode = (int)StatusCodeEnum.TokenInvalid,
                    message = StatusCodeEnum.TokenInvalid.GetEnumText(),
                    data = ""
                };
                context.Result = new JsonResult(result);
                base.OnActionExecuting(context);
                return;
            }
            else
            {
                signtoken = token.SignToken.ToString();
            }
            // 验证 Token
            bool r = SignExtension.Validate(timestamp, nonce, id, signtoken, signature);
            if (!r)
            {
                result = new ApiResult<string>
                {
                    statusCode = (int)StatusCodeEnum.HttpRequestError,
                    message = StatusCodeEnum.HttpRequestError.GetEnumText(),
                    data = ""
                };
                context.Result = new JsonResult(result);
                base.OnActionExecuting(context);
                return;
            }
            else
            {
                base.OnActionExecuting(context);
            }
        }
    }
}
